package com.atguigu.spzx.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.common.exception.GuiguException;
import com.atguigu.spzx.common.interceptor.SpzxUserInfoInterceptor;
import com.atguigu.spzx.common.util.IpUtil;
import com.atguigu.spzx.model.dto.user.UserRegistDto;
import com.atguigu.spzx.model.entity.user.UserInfo;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.model.vo.user.UserInfoVo;
import com.atguigu.spzx.user.mapper.UserInfoMapper;
import com.atguigu.spzx.user.service.UserInfoService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class UserInfoServiceImpl implements UserInfoService {
    //使用哪个RedisTemplate存的数据 就使用哪个来获取
    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    UserInfoMapper userInfoMapper;
    @Override
    public void register(UserRegistDto userRegistDto) {
        //1、校验参数
        String username = userRegistDto.getUsername();
        String password = userRegistDto.getPassword();
        String nickName = userRegistDto.getNickName();
        String code = userRegistDto.getCode();
        if(StringUtils.isEmpty(username) ||
                StringUtils.isEmpty(password)||
                StringUtils.isEmpty(nickName)||
                StringUtils.isEmpty(code)
        ){
            throw new GuiguException(ResultCodeEnum.PARAMS_ERROR);
        }
        //2、验证验证码： 获取redis中缓存的验证码 和前端提交的对比
        String codeKey = "user:regist:code:"+username;
        String codeCache = stringRedisTemplate.opsForValue().get(codeKey);
        if(!code.equals(codeCache)){
            throw new GuiguException(ResultCodeEnum.CODE_ERROR);
        }

        //3、密码加密
        String encodedPwd = DigestUtils.md5DigestAsHex(password.getBytes());

        UserInfo userInfo = new UserInfo();
        userInfo.setPassword(encodedPwd);
        userInfo.setUsername(username);
        userInfo.setNickName(nickName);
        userInfo.setAvatar("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
        userInfo.setSex(1);
        userInfo.setPhone(username);
        userInfo.setStatus(1);
        userInfo.setCreateTime(new Date());
        userInfo.setUpdateTime(new Date());

        //4、保存到数据库
        userInfoMapper.save(userInfo);
        //5、删除redis中的缓存
        stringRedisTemplate.delete(codeKey);
    }

    @Override
    public String login(UserInfo userInfo) {
        String username = userInfo.getUsername();
        String password = userInfo.getPassword();
        if(StringUtils.isEmpty(username) ||
                StringUtils.isEmpty(password)
        ){
            throw new GuiguException(ResultCodeEnum.PARAMS_ERROR);
        }
        //1、使用账号查询用户
        userInfo = userInfoMapper.findUserInfoByUserInfo(username);
        if(userInfo==null){
            throw new GuiguException(ResultCodeEnum.LOGIN_USERNAME_ERROR);
        }
        //2、判断密码是否正确
        String frontPwd = DigestUtils.md5DigestAsHex(password.getBytes());
        String dbPwd = userInfo.getPassword();
        if(!frontPwd.equals(dbPwd)){
            throw new GuiguException(ResultCodeEnum.LOGIN_PASSWORD_ERROR);
        }
        //3、登录成功：保持登录状态
        String token = UUID.randomUUID().toString().replace("-","");
        String userInfoKey = "user:login:"+ token;
        stringRedisTemplate.opsForValue().set(userInfoKey, JSON.toJSONString(userInfo) ,
                7 , TimeUnit.DAYS);
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes();
        //登录成功：更新登录日志
        userInfo.setLastLoginTime(new Date());
        userInfo.setLastLoginIp(IpUtil.getIpAddress(requestAttributes.getRequest()));
        userInfo.setUpdateTime(new Date());
        userInfoMapper.updateUserInfoById(userInfo);

        //前端查询用户状态提交的token需要和前缀拼接后才能查询到登录状态
        return token;
    }

    @Override
    public UserInfoVo getCurrentUserInfo(String token) {
        String userInfoKey = "user:login:"+ token;
        //去redis中查询登录状态 返回
        String json = stringRedisTemplate.opsForValue().get(userInfoKey);
        if(StringUtils.isEmpty(json)){
            throw new GuiguException(ResultCodeEnum.LOGIN_EXPIRE_ERROR);
        }
        UserInfo userInfo = JSON.parseObject(json, UserInfo.class);
        UserInfoVo userInfoVo = new UserInfoVo();
        userInfoVo.setAvatar(userInfo.getAvatar());
        userInfoVo.setNickName(userInfo.getNickName());
        return userInfoVo;
    }

    @Override
    public void logout() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String token = requestAttributes.getRequest().getHeader("token");
        String userInfoKey = "user:login:"+ token;
        stringRedisTemplate.delete(userInfoKey);
    }
}
